#pragma once

#include "Common.hpp"
#include "Log.hpp"
#include <functional>
#include <sys/wait.h>
#include <thread> // C++
#include "ThreadPool.hpp"

using namespace ThreadPoolModule;
using namespace LogModule;

const static int default_listen_sockfd = -1;
const static int default_backlog = 8;

using task_t = std::function<void()>;
using func_t = std::function<std::string(const std::string&,const InetAddr&)>;

class TcpServer : public NoCopy
{
public:
    TcpServer(uint16_t port,func_t func)
        : _listen_sockfd(default_listen_sockfd)
        , _port(port)
        , _running(false)
        ,_func(func)
    {
    }

    void Init()
    {
        // 1. 创建套接字
        _listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listen_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket error!";
            exit(SOCKET_ERROR);
        }
        LOG(LogLevel::INFO) << "socket success, socket: " << _listen_sockfd;

        // 2. bind套接字
        InetAddr local(_port);
        int n = bind(_listen_sockfd, CONST_CONV(local.Addr()), local.AddrLen());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind error!";
            exit(BIND_ERROR);
        }
        LOG(LogLevel::INFO) << "bind success, socket: " << _listen_sockfd;

        // 3. 设置监听套接字
        n = listen(_listen_sockfd, default_backlog);
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "listen error!";
            exit(LISTEN_ERROR);
        }
        LOG(LogLevel::INFO) << "listen success, listen_sockfd: " << _listen_sockfd;
    }

    void Service(int sockfd, const InetAddr &client)
    {
        while (true)
        {
            char buf[128];
            ssize_t s = read(sockfd, buf, sizeof(buf) - 1);
            if (s > 0)
            {
                buf[s] = 0;
                LOG(LogLevel::DEBUG) << client.StringAddr() << " # " << buf;
                
                std::string result = _func(buf,client);

                write(sockfd,result.c_str(),result.size());
            }
            else if(s == 0)
            {
                LOG(LogLevel::INFO) << client.StringAddr() << " 退出了!";
                close(sockfd);
                break;
            }
            else // s < 0
            {
                LOG(LogLevel::WARNING) << client.StringAddr() << " 异常";
                close(sockfd);
                break;
            }
        }
    }

    // // version0-单进程
    // void Start()
    // {
    //     _running = true;

    //     while (_running)
    //     {
    //         // 4. 创建已连接套接字
    //         struct sockaddr_in peer;
    //         socklen_t len = sizeof(peer);
    //         int sockfd = accept(_listen_sockfd, CONV(peer), &len);
    //         if (sockfd < 0)
    //         {
    //             LOG(LogLevel::WARNING) << "accept failed";
    //             continue;
    //         }
    //         InetAddr client(peer);
    //         LOG(LogLevel::INFO) << "accept success, client: " << client.StringAddr();

    //         Service(sockfd, client);
    //     }
    // }

    // // version1-多进程
    // void Start()
    // {
    //     _running = true;

    //     while (_running)
    //     {
    //         // 4. 创建已连接套接字
    //         struct sockaddr_in peer;
    //         socklen_t len = sizeof(peer);
    //         int sockfd = accept(_listen_sockfd, CONV(peer), &len);
    //         if (sockfd < 0)
    //         {
    //             LOG(LogLevel::WARNING) << "accept failed";
    //             continue;
    //         }
    //         InetAddr client(peer);
    //         LOG(LogLevel::INFO) << "accept success, client: " << client.StringAddr();

    //         pid_t pid = fork();
    //         if(pid < 0)
    //         {
    //             LOG(LogLevel::WARNING) << "fork failed";
    //             continue;
    //         }
    //         else if(pid == 0)
    //         {
    //             close(_listen_sockfd);
    //             // 子进程
    //             if(fork() > 0)
    //                 exit(OK);
    //             // 孙子进程
    //             Service(sockfd,client);
    //             exit(OK);
    //         }
    //         else
    //         {
    //             close(sockfd);
    //             // 父进程
    //             waitpid(pid,nullptr,0);
    //         }
    //     }
    // }

    // version2-多线程
    void Start()
    {
        _running = true;

        while (_running)
        {
            // 4. 创建已连接套接字
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sockfd = accept(_listen_sockfd, CONV(peer), &len);
            if (sockfd < 0)
            {
                LOG(LogLevel::WARNING) << "accept failed";
                continue;
            }
            InetAddr client(peer);
            LOG(LogLevel::INFO) << "accept success, client: " << client.StringAddr();

            std::thread t (&TcpServer::Service,this,sockfd,client);
            t.detach();
        }
    }

    // // version3-线程池
    // void Start()
    // {
    //     _running = true;

    //     while (_running)
    //     {
    //         // 4. 创建已连接套接字
    //         struct sockaddr_in peer;
    //         socklen_t len = sizeof(peer);
    //         int sockfd = accept(_listen_sockfd, CONV(peer), &len);
    //         if (sockfd < 0)
    //         {
    //             LOG(LogLevel::WARNING) << "accept failed";
    //             continue;
    //         }
    //         InetAddr client(peer);
    //         LOG(LogLevel::INFO) << "accept success, client: " << client.StringAddr();

    //         ThreadPool<task_t>::GetInstance()->Enqueue([this, sockfd, &client](){
    //             this->Service(sockfd, client);
    //         });
    //     }
    // }

    ~TcpServer()
    {
        close(_listen_sockfd);
    }

private:
    int _listen_sockfd;
    uint16_t _port;
    bool _running;
    func_t _func;
};